home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / fig2mfpic / fig2mfpic.c < prev    next >
C/C++ Source or Header  |  1994-06-15  |  53KB  |  2,412 lines

  1. /* 13:30 GMT +10  Thu 16 June 1994 - gt@ee.latrobe.edu.au */
  2. /* fig2mfpic 0.024 in ANSI C and traditional C */
  3. /*
  4.    Geoffrey Tobin's attempt at a "fig2mfpic" for mfpic 0.2.5,
  5.    based on Anthony Starks's Fig2MF 0.04 of Wed 28 Oct 1992,
  6.    Anthony's letter of Fri 11 Sep 1992, and
  7.    Uwe Bonnes's investigations for Uwe's transfig driver for mfpic 0.2.5.
  8.  
  9.    Note:  Fig 2.1 is the native (I/O) language of X11 `xfig' GUI drawing program.
  10.           (An older version of Fig was used in Sunview's `fig'.)
  11.           Some other programs, e.g. the unix version of gnuplot,
  12.           can output Fig 2.1 code.
  13. */
  14.  
  15. /*  fig2mfpic -- convert Fig 2.1 to mfpic 0.2.5 TeX macros
  16.  *
  17.  *  Anthony J. Starks and Geoffrey R.D. Tobin
  18.  *  ajs@msdrl.com      ecsgrt@luxor.latrobe.edu.au
  19.  *  ajs@merck.com      gt@ee.latrobe.edu.au
  20.  *
  21.  *  Uwe Bonnes
  22.  *  bon@lte.e-technik.u-erlangen.de
  23.  *
  24.  *  Scaling in inches,
  25.  *      default [x-y]scale is 1/80 inch, which is one Fig unit.
  26.  *  MFpic uses pt, not in, so fig2mfpic must convert.
  27.  *  Pen switching is local.
  28.  *  Supports 3-point arcs.
  29.  *  Token support for text.
  30.  *  Supports interpolated splines.
  31.  *  Output units: in, pt, bp, mm, cm, sp, Fig units.
  32.  *  Many input files.
  33.  *  Output to stdout.
  34.  *  Splines have floating point numbers as coordinates (Fig 2.1 spec).
  35.  *  ANSI C or traditional C.
  36.  *  Count objects, starting from 1.
  37.  *  Log file kept of all error messages.
  38.  *  In polyline, expect EPS line before points line.
  39.  *  For ANSI C, display source file, date and time of compilation.
  40.  *  Fig Object Type information supplied in TeX comments.
  41.  */
  42.  
  43. #include <math.h>
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47.  
  48. /* Fig 2.1 signature */
  49. #define FIG_SIG  "#FIG 2.1"
  50.  
  51. /* A technique for handling both Standard and traditional C compilers, */
  52. /* borrowed from the Free Software Foundation */
  53. #ifdef __STDC__
  54. #define __(X)  X
  55. #define Void void
  56. #define VOID void
  57. #else
  58. #define __(X)  ()
  59. #define Void int
  60. #define VOID
  61. #endif
  62.  
  63. char * type_name __((int code));
  64. char * diagnostic __((void));
  65. Void put_msg __((char * msg));
  66. Void Lwrite __((char * msg));
  67. Void Lflush __((void));
  68. double xs __((double x));
  69. double ys __((double y));
  70. double xt __((double x));
  71. double yt __((double y));
  72. int parse __((char * s));
  73. Void give_help __((void));
  74. int process __((char * filename));
  75. int ellipse __((FILE * figfp));
  76. int polyline __((FILE * figfp));
  77. int spline __((FILE * figfp));
  78. int read_pts __((FILE * figfp));
  79. int controls __((int npts, FILE * figfp));
  80. int text __((FILE * figfp));
  81. int arc __((FILE * figfp));
  82. int compound __((FILE * figfp));
  83. char * subtype_name __((int obj, int subobj));
  84. Void define_polydash __((void));
  85. Void finit __((void));
  86. Void cinit __((void));
  87. Void cfin __((void));
  88. Void ffin __((void));
  89. int get_line __((FILE * figfp));
  90. int next_src_line __((FILE * figfp));
  91. Void display_line __((void));
  92. int get_int __((char ** bufpa, int * ya));
  93. int get_double __((FILE * figfp, char ** bufpa, double * ya));
  94. int buffer_empty __((char * bp));
  95.  
  96. #ifndef TRUE
  97. # define TRUE  1
  98. # define FALSE 0
  99. #endif
  100.  
  101. #define SUCCESS 0
  102. #define FAILURE 1
  103.  
  104. #define MIN(a,b)  ((a) < (b) ? (a) : (b))
  105. #define MAX(a,b)  ((a) > (b) ? (a) : (b))
  106.  
  107. #define OUTPUT printf
  108.  
  109. /* write a log file? */
  110. int do_log = FALSE;
  111.  
  112. /* log file pointer */
  113. FILE * logfp = (FILE *) NULL;
  114.  
  115. /* error message */
  116.  
  117. #define MESSAGE_SLEN  255
  118. typedef char MsgType[MESSAGE_SLEN+1];
  119. MsgType Message;
  120.  
  121. /* filling gradation - is "1.2" a `magic' number? */
  122. #define dofill()  1.2-((double)area_fill/(double)FILL_BLACK)
  123.  
  124. /* pen size */
  125. #define do_pen(x)  ((x-1)*PEN_INCR)+DEF_PEN
  126.  
  127. #define VERSION    "0.024"
  128. #define MFPIC_VERSION    "0.2.5"
  129. #define GRAPHBASE_VERSION    "0.2 fig 2a"
  130.  
  131. #define O_ELLIPSE         1
  132. #define O_POLYLINE        2
  133. #define O_SPLINE          3
  134. #define O_TEXT            4
  135. #define O_ARC             5
  136. #define O_COMPOUND        6
  137. #define O_END_COMPOUND  (-6)
  138.  
  139. /* Area fill */
  140. #define UNFILLED     0
  141. #define FILL_BLACK  21
  142.  
  143. #define N_ELLIPSE   19
  144. #define N_POLYLINE  12
  145. #define N_SPLINE    11
  146. #define N_TEXT      14
  147. #define N_ARC       20
  148. #define N_COMPOUND   4
  149.  
  150. /* default pen size in pt */
  151. #define DEF_PEN   0.5
  152. #define PEN_INCR  0.1
  153.  
  154. /* DEFAULT mfpic drawing macros TeX file */
  155. #define DEF_DFILE  "mfpic.tex"
  156.  
  157. /* DEFAULT output MetaFont file : interpreted by mfpic as "figleaf.mf" */
  158. #define DEF_MF_OFILE  "figleaf"
  159.  
  160. /* DEFAULT output log file */
  161. #define DEF_LOG_FILE  "fig2mfpic.log"
  162.  
  163. #define BUF_SIZE  1024
  164. char buf[BUF_SIZE];
  165.  
  166. /* Number of TeX points (pt) in an inch (in) */
  167. #define PT_PER_INCH  72.27
  168.  
  169. /* Number of actual drawing units per pt */
  170. #define PIXEL  (PT_PER_INCH / ppi)
  171.  
  172. /* Number of default (Fig) drawing units per inch */
  173. #define DEF_PPI  80.0
  174.  
  175. /* Default maxy value (in Y drawing units) */
  176. #define DEF_MAXY  640.0
  177.  
  178. /* Pi, from Abramowitz and Stegun */
  179. #define PI  3.141592653589793238462643
  180. /* radian in degrees, from Abramowitz and Stegun */
  181. #define RADIAN  57.295779513082320876798155
  182. /* degree in radians, from Abramowitz and Stegun */
  183. #define DEGREE  0.017453292519943295769237
  184.  
  185. /* First output character's code */
  186. #define FIRST_CHAR  33
  187.  
  188. /* "fig2mfpic" program options */
  189.  
  190. #define None 0
  191. #define Real 1
  192. #define Integer 2
  193. #define String 3
  194. #define Help 4
  195. #define Unit 5
  196. #define Boolean 6
  197.  
  198. typedef struct
  199. {
  200.   char *keyword;  /* option's keyword */
  201.   int type;       /* data type of option's value */
  202.   Void *value;    /* generic pointer to option's value */
  203.   char *description;  /* description of keyword & value for option */
  204. } Options;
  205.  
  206. /* maximum allowed number of output characters */
  207. #define MAXNCHAR 256
  208.  
  209. /* number of characters output so far */
  210. int nchar = 0;
  211.  
  212. /* current line number, in current input file */
  213. int linenum = 0;
  214.  
  215. /* number of objects counted so far */
  216. int nobjs = -1;
  217.  
  218. /* object type */
  219. int obj_type = -1;
  220.  
  221. /* object subtype */
  222. int obj_subtype = -1;
  223.  
  224. /* whether object types have been listed during this run */
  225. int listed_types = FALSE;
  226.  
  227. /* pixels [input units] per inch */
  228. /* 1 Fig unit = 1 inch / ppi */
  229. double ppi = DEF_PPI;
  230.  
  231. /* coordinate system = orientation of Y axis */
  232. #define Y_UP    1
  233. #define Y_DOWN  2
  234. int coord_sys = Y_DOWN;  /* usual with Fig */
  235.  
  236. /* I prefer input and output units to coincide */
  237. double oupi = DEF_PPI;  /* output units per inch */
  238. double ioc = 1.0;  /* input to output unit conversion factor */
  239.  
  240. /* calculated bounding box of a picture */
  241. double bxl, bxu, byl, byu;
  242. int bbbegun = 0;  /* no lower bound yet for BB for current picture */
  243.  
  244. /* options */
  245. int help;  /* help flag */
  246. int debug;  /* debug flag */
  247. int char_code = 33;  /* initial char code */
  248. double mfpen;  /* global pen width (pt) */
  249. char * o_unit="Fig";  /* output unit (default is 1 Fig unit) */
  250. double xscale = 1.0;  /* 1 X drawing unit = xscale * output unit */
  251. double yscale = 1.0;
  252. double xl;  /* character bounds, in X and Y drawing units */
  253. double yl;
  254. double xu;
  255. double yu;
  256. double maxy;  /* maximum Y value (Y drawing units) */
  257. char * mf_ofile="";    /* output MF file name */
  258. char *draw_macros="";  /* mfpic drawing macros TeX file name */
  259. char *log_file="";     /* log file name */
  260.  
  261. char *progname="";  /* command line name of this program */
  262. char *curfigfile="";   /* current input file */
  263.  
  264. Options opts[]  =
  265. {
  266.   {"-?",  Help, &help, "Help request"},
  267.   {"-d",  Boolean, &debug, "List input file, with line numbers"},
  268.   {"-code",  Integer, &char_code, "First character's code : not effective"},
  269.   {"-pen",  Real, &mfpen, "Default pen width (pt)"},
  270.   {"-u",  Unit, &o_unit, "Output unit name"},
  271.   {"-xscale",  Real, &xscale, "X unit (in output units)"},
  272.   {"-yscale",  Real, &yscale, "Y unit (in output units)"},
  273.   {"-xneg",  Real, &xl, "Most negative X value (X units)"},
  274.   {"-xpos",  Real, &xu, "Most positive X value (X units)"},
  275.   {"-yneg",  Real, &yl, "Most negative Y value (Y units)"},
  276.   {"-ypos",  Real, &yu, "Most positive Y value (Y units)"},
  277.   {"-top",  Real, &maxy, "Top of drawing (Y units)"},
  278.   {"-mf",  String, &mf_ofile, "Output METAFONT file"},
  279.   {"-tex",  String, &draw_macros, "mfpic TeX drawing macros file"},
  280.   {"-log",  String, &log_file, "fig2mfpic log file"},
  281.   {NULL,  None,    NULL, ""}
  282. };  /* opts[] */
  283.  
  284.  
  285. /* FUNCTIONS */
  286.  
  287.  
  288. /* return name of object type from given code */
  289. char *
  290. type_name
  291. #ifdef __STDC__
  292.   (int code)
  293. #else
  294.   (code)
  295.   int code;
  296. #endif
  297. {
  298.   char * name = "unknown";
  299.  
  300.   switch (code)
  301.   {
  302.     case O_ELLIPSE:
  303.       name = "ellipse";
  304.       break;
  305.     case O_POLYLINE:
  306.       name = "polyline";
  307.       break;
  308.     case O_SPLINE:
  309.       name = "spline";
  310.       break;
  311.     case O_TEXT:
  312.       name = "text";
  313.       break;
  314.     case O_ARC:
  315.       name = "arc";
  316.       break;
  317.     case O_COMPOUND:
  318.       name = "compound";
  319.       break;
  320.     case O_END_COMPOUND:
  321.       name = "end compound";
  322.       break;
  323.     default:
  324.       name = "unknown";
  325.       break;
  326.   }
  327.   return (name);
  328. } /* type_name */
  329.  
  330.  
  331. char *
  332. diagnostic (VOID)
  333. {
  334.   extern char *curfigfile;
  335.   extern int nobjs;
  336.   extern int obj_type;
  337.   extern int linenum;
  338.   extern MsgType Message;
  339.   char * Diagnostic = Message;
  340.  
  341.   sprintf (Diagnostic,
  342.            " : file \"%s\", object # %d, type %s (%d %d), at line %d\n",
  343.            curfigfile, nobjs+1,
  344.            subtype_name (obj_type, obj_subtype), obj_type, obj_subtype,
  345.            linenum);
  346.   return (Diagnostic);
  347. } /* diagnostic */
  348.  
  349. /* write a diagnostic message to stderr and to logfp */
  350. Void
  351. put_msg
  352. #ifdef __STDC__
  353.   (char * msg)
  354. #else
  355.   (msg)
  356.   char * msg;
  357. #endif
  358. {
  359.   if (!debug)  /* avoid double display */
  360.   {
  361.     display_line();
  362.   }
  363.   Lwrite ("! ");
  364.   Lwrite (msg);
  365.   Lwrite (diagnostic());
  366.   Lflush ();
  367. } /* put_msg */
  368.  
  369. /* write to stderr and to logfp */
  370. Void
  371. Lwrite (char * msg)
  372. {
  373.   extern int do_log;
  374.   fprintf (stderr, "%s", msg);
  375.   if (do_log)
  376.   {
  377.     fprintf (logfp, "%s", msg);
  378.   }
  379. } /* Lwrite */
  380.  
  381. /* flush both stderr and logfp */
  382. Void
  383. Lflush (void)
  384. {
  385.   fflush (stderr);
  386.   if (do_log)
  387.   {
  388.     fflush (logfp);
  389.   }
  390. } /* Lflush */
  391.    
  392. double
  393. xs
  394. #ifdef __STDC__
  395.   (double xr)
  396. #else
  397.   (xr)
  398.   double xr;
  399. #endif
  400. {
  401.   return (ioc * xr);
  402. } /* xs */
  403.  
  404. double
  405. ys
  406. #ifdef __STDC__
  407.   (double yr)
  408. #else
  409.   (yr)
  410.   double yr;
  411. #endif
  412. {
  413.   return (ioc * yr);
  414. } /* ys */
  415.  
  416. double
  417. xt
  418. #ifdef __STDC__
  419.   (double x)
  420. #else
  421.   (x)
  422.   double x;
  423. #endif
  424. {
  425.   return (ioc * x);
  426. } /* xt */
  427.  
  428. double
  429. yt
  430. #ifdef __STDC__
  431.    (double y)
  432. #else
  433.   (y)
  434.   double y;
  435. #endif
  436. {
  437.   return (ioc * (maxy-y));
  438. } /* yt */
  439.  
  440.  
  441. int
  442. main
  443. #ifdef __STDC__
  444.   (int argc, char * argv[])
  445. #else
  446.   (argc, argv)
  447.   int argc;
  448.   char * argv[];
  449. #endif
  450. {
  451.   progname = argv[0];  /* this program */
  452.   curfigfile = "Standard Input";  /* current input file */
  453.   linenum=0;  /* no line read yet */
  454.  
  455.   /* initial values of options */
  456.   help=0;  /* no help */
  457.   char_code=FIRST_CHAR;  /* first character has char code FIRST_CHAR */
  458.   mfpen=DEF_PEN;  /* pen diameter (pt) */
  459.   o_unit = "Fig";
  460.   xscale=1.0;  /* drawing units (in output units) */
  461.   yscale=1.0;
  462.   xl=0.0;  /* xl, xu, yl, yu : size of picture in drawing units */
  463.   xu=DEF_MAXY;
  464.   yl=0.0;
  465.   yu=DEF_MAXY;
  466.   maxy=DEF_MAXY;
  467.   mf_ofile=DEF_MF_OFILE;  /* use default MF drawing macros */
  468.   draw_macros=DEF_DFILE;  /* use default TeX drawing macros */
  469.   log_file=DEF_LOG_FILE;  /* write to default log file */
  470.  
  471.   if ((logfp = fopen (log_file, "w")) == (FILE *) NULL)
  472.   {
  473.     do_log = FALSE;
  474.   }
  475.   else
  476.   {
  477.     do_log = TRUE;
  478.   }
  479.  
  480.   if (argc < 2)  /* no cmdline arguments, so give help */
  481.     give_help();
  482.   else  /* treat each argument as an option or an input filename */
  483.   {
  484.     int i;
  485.     for (i=1; i < argc; i++)
  486.       parse (argv[i]);
  487.   }
  488.  
  489.   ffin();  /* close mfpic output, if there was any */
  490.  
  491.   return (SUCCESS);
  492. }
  493. /* main */
  494.  
  495.  
  496. int
  497. parse
  498. #ifdef __STDC__
  499.   (char * s)
  500. #else
  501.   (s)
  502.   char * s;
  503. #endif
  504. {
  505.   int optnum;
  506.   char *strchr();
  507.   double atof();
  508.   int atoi();
  509.  
  510.   for (optnum=0; opts[optnum].keyword != NULL; optnum++)
  511.   {
  512.     if (strncmp (s, opts[optnum].keyword, strlen (opts[optnum].keyword)) == 0)
  513.     {
  514.       switch (opts[optnum].type)
  515.       {
  516.         case None:
  517.           break;
  518.         case Real:
  519.           * (double *) opts[optnum].value = atof (strchr (s, '=')+1);
  520.           break;
  521.         case Integer:
  522.           * (int *) opts[optnum].value = atoi (strchr (s, '=')+1);
  523.           break;
  524.         case String:
  525.           * (char * *) opts[optnum].value = strchr (s, '=')+1;
  526.           break;
  527.         case Help:
  528.           give_help();
  529.           break;
  530.         case Unit:
  531.           {
  532.             char * unit = strchr (s, '=')+1;
  533.             * (char * *) opts[optnum].value = unit;
  534.             check_unit (unit);
  535.           }
  536.           break;
  537.         case Boolean:  /* FALSE by default */
  538.           * (int *) opts[optnum].value = TRUE;
  539.           break;
  540.       }
  541.       return (optnum);
  542.     }
  543.   }
  544.   /* this command line argument is not a known option */
  545.   /* so assume it's a filename */
  546.   process (s);
  547.   return (optnum);
  548. }
  549. /* parse */
  550.  
  551. Void
  552. give_help (VOID)
  553. {
  554.   char * typename = "unknown type";
  555.   int i;
  556.   MsgType Advice;
  557.  
  558.   sprintf (Advice, "usage:  %s  ", progname);
  559.   Lwrite (Advice);
  560.   Lwrite ("[infile] [... infile] [> outfile]");
  561.   Lwrite ("\n");
  562.   Lflush ();
  563.  
  564.   for (i=0; opts[i].keyword != NULL; i++)
  565.   {
  566.     switch (opts[i].type)
  567.     {
  568.       case Real:  typename = "real";  break;
  569.       case Integer:  typename = "integer";  break;
  570.       case String:  typename = "string";  break;
  571.       default:  typename = "none";  break;
  572.     }
  573.     Lwrite ("    ");
  574.     switch (opts[i].type)
  575.     {
  576.       case None:
  577.       case Help:
  578.       case Boolean:
  579.         sprintf (Advice, "[%s]", opts[i].keyword);
  580.         Lwrite (Advice);
  581.         break;
  582.       default:
  583.         sprintf (Advice, "[%s=<%s>]", opts[i].keyword, typename);
  584.         Lwrite (Advice);
  585.         break;
  586.     }
  587.     Lwrite ("    ");
  588.     sprintf (Advice, "%s", opts[i].description);
  589.     Lwrite (Advice);
  590.     Lwrite ("\n");
  591.     Lflush ();
  592.   }
  593.   Lwrite ("If an \"infile\" is \"-\", then standard input is read.\n");
  594.   Lwrite ("The mfpic TeX drawing file goes to standard output.\n");
  595.   Lwrite ("Messages, such as this, go to standard error.\n");
  596.   Lflush ();
  597. }
  598. /* give_help */
  599.   
  600. typedef struct
  601. {
  602.   char * name;   /* name of unit */
  603.   double value;  /* value of 1 inch / 1 unit, i.e. the number of units per inch */
  604. } Units;
  605.  
  606. Units units[] =
  607. {
  608.   {"in", 1.0},
  609.   {"pt", 72.27},
  610.   {"bp", 72.0},
  611.   {"mm", 25.4},
  612.   {"cm", 2.54},
  613.   {"sp", 72.27 * 65536},
  614.   {"Fig", 80.0},
  615.   {NULL, 0.0},
  616. };  /* units[] */
  617.  
  618. int
  619. check_unit
  620. #ifdef __STDC__
  621.   (char * unit)
  622. #else
  623.   (unit)
  624.   char * unit;
  625. #endif
  626. {
  627.   extern MsgType Message;
  628.   int unum;
  629.   for (unum=0; units[unum].name != NULL; unum++)
  630.   {
  631.     if (strncmp (unit, units[unum].name, strlen (units[unum].name)) == 0)
  632.     {
  633.       oupi = units[unum].value;
  634.       return (unum);
  635.     }
  636.   }
  637.   sprintf (Message, "\"%s\" is an unknown unit!\n", unit);
  638.   Lwrite (Message);
  639.   Lflush ();
  640.   return (unum);
  641. }
  642. /* check_unit */
  643.  
  644. int
  645. process
  646. #ifdef __STDC__
  647.   (char * filename)
  648. #else
  649.   (filename)
  650.   char * filename;
  651. #endif
  652. {
  653.   extern MsgType Message;
  654.   extern int listed_types;
  655.   FILE * figfp;
  656.  
  657.   if (filename[0] == '-')
  658.   {
  659.     curfigfile = "Standard Input";
  660.     figfp = stdin;
  661.   }
  662.   else
  663.   {
  664.     curfigfile=filename;
  665.     if ((figfp = fopen (filename, "r")) == NULL)
  666.     {
  667.       sprintf (Message,
  668.         "%s: cannot open the input file \"%s\"\n",
  669.         progname, filename);
  670.       Lwrite (Message);
  671.       Lflush ();
  672.       return (FAILURE);
  673.     }
  674.   }
  675.  
  676.   linenum = 0;
  677.   /* The very first line in a Fig file must be a particular comment */
  678.   get_line (figfp);
  679.   /* Fig and version identification comment, and its length */
  680.   if (strncmp (buf, FIG_SIG, strlen (FIG_SIG)) != 0)
  681.   {
  682.     put_msg ("Not a Fig 2.1 signature");
  683.     sprintf (Message, "Expected first line to be \"%s\"\n", FIG_SIG);
  684.     Lwrite (Message);
  685.     Lflush ();
  686.     return (FAILURE);
  687.   }
  688.   next_src_line (figfp);
  689.   if (sscanf (buf, "%lf%d\n", &ppi, &coord_sys) != 2)
  690.   {
  691.     put_msg ("ppi or coord_sys missing or not in \"real integer\" format");
  692.     return (FAILURE);
  693.   }
  694.   /* For Fig 2.1, ppi = DEF_PPI = 80.0 pixels per inch, */
  695.   /* and the coord_sys = Y_DOWN = 2, meaning origin at top left */
  696.  
  697.   ioc = oupi / ppi;  /* current number of output units per input unit */
  698.  
  699.   {
  700.     /* First input Fig file */
  701.     static int once = 0;
  702.     if (once == 0)
  703.     {
  704.       finit();  /* start of the (sole) TeX output file */
  705.       once = 1;
  706.     }
  707.   }
  708.  
  709.   cinit();  /* One MF character per Fig picture */
  710.  
  711.   for (nobjs = 0;  next_src_line (figfp) > 0;  ++ nobjs)
  712.   {
  713.     /* object type */
  714.     if (sscanf (buf, "%d", &obj_type) != 1)
  715.     {
  716.       put_msg ("Incorrect object type code (need integer)");
  717.       return (FAILURE);
  718.     }
  719.  
  720.     if (obj_type == O_COMPOUND || obj_type == O_END_COMPOUND)
  721.     {
  722.       OUTPUT ("%% %d : %s (%d)\n",
  723.               nobjs+1,
  724.               type_name (obj_type), obj_type);
  725.     }
  726.     else
  727.     {
  728.       /* object subtype */
  729.       if (sscanf (buf, "%*d %d", &obj_subtype) != 1)
  730.       {
  731.         put_msg ("Incorrect object subtype code (need integer)");
  732.         return (FAILURE);
  733.       }
  734.  
  735.       OUTPUT ("%% %d : %s (%d %d)\n",
  736.               nobjs+1,
  737.               subtype_name (obj_type, obj_subtype), obj_type, obj_subtype);
  738.     }
  739.  
  740.     switch (obj_type)
  741.     {
  742.       case O_ELLIPSE:
  743.         ellipse (figfp);
  744.         break;
  745.       case O_POLYLINE:
  746.         polyline (figfp);
  747.         break;
  748.       case O_SPLINE:
  749.         spline (figfp);
  750.         break;
  751.       case O_TEXT:
  752.         text (figfp);
  753.         break;
  754.       case O_ARC:
  755.         arc (figfp);
  756.         break;
  757.       case O_COMPOUND:
  758.         compound (figfp);
  759.         break;
  760.       case O_END_COMPOUND:
  761.         end_compound (figfp);
  762.         break;
  763.       default:
  764.         sprintf (Message, "Object omitted");
  765.         put_msg (Message);
  766.         if (!listed_types)
  767.         {
  768.           Lwrite ("Known object types are:\n");
  769.           sprintf (Message, "    ellipse (%d)\n", O_ELLIPSE);
  770.           Lwrite (Message);
  771.           sprintf (Message, "    polyline (%d)\n", O_POLYLINE);
  772.           Lwrite (Message);
  773.           sprintf (Message, "    spline (%d)\n", O_SPLINE);
  774.           Lwrite (Message);
  775.           sprintf (Message, "    text (%d)\n", O_TEXT);
  776.           Lwrite (Message);
  777.           sprintf (Message, "    arc (%d)\n", O_ARC);
  778.           Lwrite (Message);
  779.           sprintf (Message, "    compound (%d)\n", O_COMPOUND);
  780.           Lwrite (Message);
  781.           sprintf (Message, "    end_compound (%d)\n", O_END_COMPOUND);
  782.           Lwrite (Message);
  783.           Lflush ();
  784.           listed_types = TRUE;
  785.         }
  786.         break;
  787.     }
  788.   }
  789.  
  790.   cfin();
  791.  
  792.   if (figfp != stdin)
  793.     fclose (figfp);
  794.  
  795.   return (SUCCESS);
  796. }
  797. /* process */
  798.  
  799.  
  800. /* Line styles */
  801.  
  802. #define SOLID_LINE   0
  803. #define DASH_LINE    1
  804. #define DOTTED_LINE  2
  805.  
  806. /* Dimension of a dot in dotted line style (pt) */
  807. #define DOT_SIZE  1.0
  808.  
  809.  
  810. /* Ellipse objects */
  811. /* Ellipse or circle, described by radius (radii) or diameter(s) */
  812. /* Subtypes: */
  813. #define T_ELLIPSE_BY_RAD  1
  814. #define T_ELLIPSE_BY_DIA  2
  815. #define T_CIRCLE_BY_RAD   3
  816. #define T_CIRCLE_BY_DIA   4
  817.  
  818. int
  819. ellipse
  820. #ifdef __STDC__
  821.   (FILE * figfp)
  822. #else
  823.   (figfp)
  824.   FILE * figfp;
  825. #endif
  826. {
  827.   int  n;
  828.   int  type,
  829.        subtype,
  830.        line_style,
  831.        line_thickness,  /* pixels */
  832.        color,
  833.        depth,
  834.        pen,  /* unused in Fig */
  835.        area_fill;    /* 0: not filled, 1 : white, ..., 21: black */
  836.   double  style_val;    /* pixels; for dash lines, length of on/off dashes */
  837.                         /*         for dot lines, gap b/w dots */
  838.   int  dir;
  839.   double  angle;
  840.   int  cx,  /* cx, cy : centre */
  841.        cy,
  842.        rx,  /* rx, ry : radii */
  843.        ry,
  844.        sx,  /* sx, sy, ex, ey : ellipse's bounding box */
  845.        sy,
  846.        ex,
  847.        ey;
  848.  
  849.   n = sscanf (buf, "%d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d",
  850.     &type,
  851.     &subtype,
  852.     &line_style,
  853.     &line_thickness,
  854.     &color,
  855.     &depth,
  856.     &pen,
  857.     &area_fill,
  858.     &style_val,
  859.     &dir,
  860.     &angle,
  861.     &cx,
  862.     &cy,
  863.     &rx,
  864.     &ry,
  865.     &sx,
  866.     &sy,
  867.     &ex,
  868.     &ey);
  869.   if (n != N_ELLIPSE)
  870.   {
  871.     put_msg ("Malformed circle or ellipse");
  872.     return n;
  873.   }
  874.  
  875.   {
  876.     int fx, fy;
  877.     if (subtype == T_CIRCLE_BY_RAD || subtype == T_ELLIPSE_BY_RAD)
  878.     {
  879.       fx = 2 * cx - ex;
  880.       fy = 2 * cy - ey;
  881.     }
  882.     else
  883.     {
  884.       fx = sx;
  885.       fy = sy;
  886.     }
  887.     if (bbbegun)
  888.     {
  889.       bxl = MIN (bxl, ex);  bxl = MIN (bxl, fx);
  890.       bxu = MAX (bxu, ex);  bxu = MAX (bxu, fx);
  891.       byl = MIN (byl, ey);  byl = MIN (byl, fy);
  892.       byu = MAX (byu, ey);  byu = MAX (byu, fy);
  893.     }
  894.     else
  895.     {
  896.       bxl = MIN (ex, fx);
  897.       bxu = MAX (ex, fx);
  898.       byl = MIN (ey, fy);
  899.       byu = MAX (ey, fy);
  900.       bbbegun = 1;
  901.     }
  902.   }
  903.  
  904.   if (line_thickness > 1)
  905.     OUTPUT ("  \\pen{%.2lfpt}\n", do_pen (line_thickness));
  906.  
  907.   if (subtype == T_CIRCLE_BY_RAD || subtype == T_CIRCLE_BY_DIA)
  908.   {
  909.     if (area_fill == FILL_BLACK)
  910.       OUTPUT ("  \\cdisk");
  911.     else if (area_fill < FILL_BLACK && area_fill > UNFILLED)
  912.     {
  913.       OUTPUT ("  \\shadespace=%lfpt\n", dofill());
  914.       OUTPUT ("  \\circshade");
  915.     }
  916.     else
  917.       OUTPUT ("  \\circle");
  918.  
  919.     OUTPUT ("{(%lf,%lf),%lf}\n", xt(cx), yt(cy), xs(rx));
  920.   }
  921.   else if (subtype == T_ELLIPSE_BY_RAD || subtype == T_ELLIPSE_BY_DIA)
  922.   {
  923.     if (area_fill == FILL_BLACK)
  924.       OUTPUT ("  \rotatededisk");
  925.     else if (area_fill < FILL_BLACK && area_fill > UNFILLED)
  926.     {
  927.       OUTPUT ("  \\shadespace=%lfpt\n", dofill());
  928.       OUTPUT ("  \\rotatedellshade");
  929.     }
  930.     else
  931.       OUTPUT ("  \\rotatedellipse");
  932.  
  933.     OUTPUT ("{(%lf,%lf),%lf,%lf,%lf}\n",
  934.       xt(cx), yt(cy), xs(rx), ys(ry), angle * RADIAN);
  935.   }
  936.  
  937.   if (line_thickness > 1)
  938.     OUTPUT ("  \\pen{%.2lfpt}\n", mfpen);
  939.  
  940.   return n;
  941. }
  942. /* ellipse */
  943.  
  944.  
  945. /* Polyline objects */
  946. /* Subtypes: */
  947. /* Many of these remain unimplemented in fig2mfpic */
  948. #define T_POLYLINE  1
  949. #define T_BOX       2
  950. #define T_POLYGON   3
  951. #define T_ARC_BOX   4
  952. #define T_EPS_BOX   5
  953.  
  954. #define EPS_UPRIGHT  0
  955. #define EPS_FLIPPED  1
  956.  
  957. /* Maximum length of name of EPSF file */
  958. #define EPSF_SLEN  100
  959.  
  960. int
  961. polyline
  962. #ifdef __STDC__
  963.   (FILE * figfp)
  964. #else
  965.   (figfp)
  966.   FILE * figfp;
  967. #endif
  968. {
  969.   int  npts_read;
  970.   int  n;
  971.   int  type,
  972.     subtype,
  973.     line_style,
  974.     line_thickness,
  975.     color,
  976.     depth,
  977.     pen,
  978.     area_fill;
  979.  
  980.   double  style_val;
  981.  
  982.   int  radius,  /* for rounded corners of boxes */
  983.     fa,  /* Forward arrow : not yet interpreted in fig2mfpic */
  984.     ba,  /* Backward arrow : not yet interpreted in fig2mfpic */
  985.     at,
  986.     as,
  987.     eflag;
  988.  
  989.   double  athick,
  990.     awidth,
  991.     aht;
  992.  
  993.   char  epsfile[EPSF_SLEN+1];
  994.  
  995.   npts_read = 0;
  996.   n = sscanf (buf, "%d%d%d%d%d%d%d%d%lf%d%d%d",
  997.     &type,
  998.     &subtype,
  999.     &line_style,
  1000.     &line_thickness,
  1001.     &color,
  1002.     &depth,
  1003.     &pen,
  1004.     &area_fill,
  1005.     &style_val,
  1006.     &radius,
  1007.     &fa,
  1008.     &ba);
  1009.  
  1010.   if (n != N_POLYLINE)
  1011.   {
  1012.     put_msg ("Malformed polyline");
  1013.     return npts_read;
  1014.   }
  1015.  
  1016.   if (fa)
  1017.   {
  1018.     next_src_line (figfp);
  1019.     sscanf (buf, "%d%d%lf%lf%lf\n", &at, &as, &athick, &awidth, &aht);
  1020.   }
  1021.   if (ba)
  1022.   {
  1023.     next_src_line (figfp);
  1024.     sscanf (buf, "%d%d%lf%lf%lf\n", &at, &as, &athick, &awidth, &aht);
  1025.   }
  1026.  
  1027.   if (line_thickness > 1)
  1028.     OUTPUT ("  \\pen{%.2lfpt}%%\n", do_pen (line_thickness));
  1029.  
  1030.   /* filling or shading */
  1031.  
  1032.   if (area_fill == FILL_BLACK)  /* fill with black */
  1033.   {
  1034.     OUTPUT ("  \\polyfill");
  1035.   }
  1036.   else if (area_fill < FILL_BLACK && area_fill > UNFILLED)  /* shade */
  1037.   {
  1038.     OUTPUT ("  \\shadespace=%lfpt%%\n", dofill());
  1039.     OUTPUT ("  \\polyshade");
  1040.   }
  1041.   else  /* no fill or shade */
  1042.   {
  1043.     if (line_style == SOLID_LINE)
  1044.       OUTPUT ("  \\polyline");
  1045.     else if (line_style == DASH_LINE)
  1046.     {
  1047.       OUTPUT ("  \\dashlen=%lfpt%%\n", style_val);
  1048.       OUTPUT ("  \\dashspace=%lfpt%%\n", style_val);
  1049.       OUTPUT ("  \\polydash");
  1050.     }
  1051.     else /* DOTTED_LINE */
  1052.     {
  1053.       OUTPUT ("  \\dashlen=%lfpt%%\n", DOT_SIZE);
  1054.       OUTPUT ("  \\dashspace=%lfpt%%\n", style_val);
  1055.       OUTPUT ("  \\polydash");
  1056.     }
  1057.   }
  1058.  
  1059.   /* eps line is before points line, according to transfig source */
  1060.  
  1061.   if (subtype == T_EPS_BOX)
  1062.   {
  1063.     next_src_line (figfp);
  1064.     sscanf (buf, "%d%s", &eflag, epsfile);
  1065.   }
  1066.  
  1067.   OUTPUT ("{%%\n");
  1068.   npts_read = read_pts (figfp);
  1069.   OUTPUT ("}\n");
  1070.  
  1071.   if (line_thickness > 1)
  1072.     OUTPUT ("  \\pen{%.2lfpt}%%\n", mfpen);
  1073.  
  1074.   return npts_read;
  1075. }
  1076. /* polyline */
  1077.  
  1078.  
  1079. /* Spline objects */
  1080. /* Subtypes: */
  1081. /* Normal splines (`B-splines') are here incorrectly implemented */
  1082. #define T_OPEN_NORMAL          0
  1083. #define T_CLOSED_NORMAL        1
  1084. #define T_OPEN_INTERPOLATED    2
  1085. #define T_CLOSED_INTERPOLATED  3
  1086.  
  1087. int
  1088. spline
  1089. #ifdef __STDC__
  1090.   (FILE * figfp)
  1091. #else
  1092.   (figfp)
  1093.   FILE * figfp;
  1094. #endif
  1095. {
  1096.   int  n;
  1097.   int  npts_read;
  1098.   int  type,
  1099.     line_style,
  1100.     subtype,
  1101.     line_thickness,
  1102.     color,
  1103.     depth,
  1104.     pen,
  1105.     area_fill,
  1106.     fa,
  1107.     ba,
  1108.     at,
  1109.     as;
  1110.  
  1111.   double  style_val,
  1112.     athick,
  1113.     awidth,
  1114.     aht;
  1115.  
  1116.   npts_read = 0;
  1117.   n = sscanf (buf, "%d%d%d%d%d%d%d%d%lf%d%d",
  1118.        &type,
  1119.        &subtype,
  1120.        &line_style,
  1121.        &line_thickness,
  1122.        &color,
  1123.        &depth,
  1124.        &pen,
  1125.        &area_fill,
  1126.        &style_val,
  1127.        &fa,
  1128.        &ba);
  1129.   if (n != N_SPLINE)
  1130.   {
  1131.     put_msg ("Malformed spline");
  1132.     return npts_read;
  1133.   }
  1134.  
  1135.   if (fa)
  1136.   {
  1137.     next_src_line (figfp);
  1138.     sscanf (buf, "%d%d%lf%lf%lf\n", &at, &as, &athick, &awidth, &aht);
  1139.   }
  1140.   if (ba)
  1141.   {
  1142.     next_src_line (figfp);
  1143.     sscanf (buf, "%d%d%lf%lf%lf\n", &at, &as, &athick, &awidth, &aht);
  1144.   }
  1145.  
  1146.   if (line_thickness > 1)
  1147.     OUTPUT ("  \\pen{%.2lfpt}%%\n", do_pen (line_thickness));
  1148.  
  1149.   if (subtype == T_OPEN_NORMAL || subtype == T_CLOSED_NORMAL)
  1150.   /* B-spline - very roughly */
  1151.   {
  1152.     if (subtype == T_OPEN_NORMAL)  /* open B-spline */
  1153.     {
  1154.         OUTPUT ("  \\curve");
  1155.     }
  1156.     else if (subtype == T_CLOSED_NORMAL)  /* closed B-spline */
  1157.     {
  1158.       if (area_fill == FILL_BLACK)  /* fill with black */
  1159.       {
  1160.         OUTPUT ("  \\cyclefill");
  1161.       }
  1162.       else if (area_fill < FILL_BLACK && area_fill > UNFILLED)  /* shade */
  1163.       {
  1164.         OUTPUT ("  \\shadespace=%lfpt%%\n", dofill());
  1165.         OUTPUT ("  \\cycleshade");
  1166.       }
  1167.       else  /* neither fill nor shade */
  1168.       {
  1169.         OUTPUT ("  \\cyclic");
  1170.       }
  1171.     }
  1172.  
  1173.     /* control points - wrongly treated for B-spline */
  1174.     OUTPUT ("{%%\n");
  1175.     npts_read = read_pts (figfp);
  1176.     OUTPUT ("}\n");
  1177.   }
  1178.   else if (subtype == T_OPEN_INTERPOLATED || subtype == T_CLOSED_INTERPOLATED)
  1179.   {
  1180.     OUTPUT ("  \\mfcmd {%%\n");
  1181.  
  1182.     if (subtype == T_OPEN_INTERPOLATED)  /* open I-spline */
  1183.     {
  1184.         OUTPUT ("  ispline (false)");
  1185.     }
  1186.     else if (subtype == T_CLOSED_INTERPOLATED)  /* closed I-spline */
  1187.     {
  1188.       if (area_fill == FILL_BLACK)  /* fill with black */
  1189.       {
  1190.         OUTPUT ("  isplineshade (0)");
  1191.       }
  1192.       else if (area_fill < FILL_BLACK && area_fill > UNFILLED)  /* shade */
  1193.       {
  1194.         OUTPUT ("  isplineshade (%lfpt)", dofill());
  1195.       }
  1196.       else  /* neither fill nor shade */
  1197.       {
  1198.         OUTPUT ("  ispline (true)");
  1199.       }
  1200.     }
  1201.     
  1202.     /* interpolation ("key") points */
  1203.     OUTPUT ("  ( \n");
  1204.     npts_read = read_pts (figfp);
  1205.     OUTPUT ("  ) \n");
  1206.  
  1207.     /* control points */
  1208.     OUTPUT ("  ( \n");
  1209.     npts_read = controls (npts_read, figfp);
  1210.     OUTPUT ("  ) \n");
  1211.  
  1212.     OUTPUT ("  }\n");  /* end "\mfcmd" */
  1213.   }
  1214.  
  1215.   if (line_thickness > 1)
  1216.     OUTPUT ("  \\pen{%.2lfpt}\n", mfpen);
  1217.  
  1218.   return npts_read;
  1219. }
  1220. /* spline */
  1221.  
  1222.  
  1223. /* Sentinel signalling end of coordinate pair list */
  1224. #define END_COORD  9999
  1225.  
  1226. int
  1227. read_pts
  1228. #ifdef __STDC__
  1229.   (FILE * figfp)
  1230. #else
  1231.   (figfp)
  1232.   FILE * figfp;
  1233. #endif
  1234. {
  1235.   extern MsgType Message;
  1236.   char * bufp = buf;   /* pointer to current buffer position */
  1237.   int more = 1;  /* any more coordinates? */
  1238.   int npts_read = 0;    /* number of coordinate pairs */
  1239.  
  1240.   /* Read key points line from Fig file into buffer */
  1241.   next_src_line (figfp);
  1242.  
  1243.   while (more)
  1244.   {
  1245.     int x, y;
  1246.     int n;
  1247.  
  1248.     /* read X and Y coordinates of a point */
  1249.     if (!get_int (&bufp, &x))
  1250.     {
  1251.       put_msg ("Missing X coordinate (expect an integer),");
  1252.       sprintf (Message, "  point %d anticipated,\n", npts_read+1);
  1253.       Lwrite (Message);
  1254.       sprintf (Message, "  coord. after byte %ld in line.\n", bufp - buf);
  1255.       Lwrite (Message);
  1256.       Lflush ();
  1257.       more = 0;
  1258.     }
  1259.     else if (!get_int (&bufp, &y))
  1260.     {
  1261.       put_msg ("Missing Y coordinate (expect an integer),");
  1262.       sprintf (Message, "  amidst point %d,\n", npts_read+1);
  1263.       Lwrite (Message);
  1264.       sprintf (Message, "  coord. after byte %ld in line.\n", bufp - buf);
  1265.       Lwrite (Message);
  1266.       Lflush ();
  1267.       more = 0;
  1268.     }
  1269.     else if (x == END_COORD)
  1270.     {
  1271.       if (y != END_COORD)
  1272.       {
  1273.         sprintf (Message, "final Y coordinate is not %d", END_COORD);
  1274.         put_msg (Message);
  1275.       }
  1276.       more = 0;
  1277.     }
  1278.     else
  1279.     {
  1280.       if (bbbegun)
  1281.       {
  1282.         bxl = MIN (bxl, x);
  1283.         bxu = MAX (bxu, x);
  1284.         byl = MIN (byl, y);
  1285.         byu = MAX (byu, y);
  1286.       }
  1287.       else
  1288.       {
  1289.         bxl = bxu = x;
  1290.         byl = byu = y;
  1291.         bbbegun = 1;
  1292.       }
  1293.  
  1294.       /* write key point coordinates to TeX file */
  1295.  
  1296.       if (npts_read > 0)
  1297.         OUTPUT (",\n");
  1298.       OUTPUT ("       (%lf, %lf)", xt(x), yt(y));
  1299.       ++ npts_read;
  1300.       more = 1;
  1301.     }
  1302.   }
  1303.  
  1304.   if (npts_read < 1)
  1305.   {
  1306.     put_msg ("No key points");
  1307.   }
  1308.  
  1309.   return npts_read;
  1310. }
  1311. /* read_pts */
  1312.  
  1313. int
  1314. buffer_empty
  1315. #ifdef __STDC__
  1316.   (char * bp)
  1317. #else
  1318. int
  1319.   (bp)
  1320.   char * bp;
  1321. #endif
  1322. {
  1323.   int empty = FALSE;
  1324.   if (bp == NULL)
  1325.     empty = TRUE;
  1326.   else
  1327.   {
  1328.     while (*bp != '\0' && isspace (*bp))
  1329.       ++ bp;
  1330.     empty = (*bp == '\0');
  1331.   }
  1332.   return empty;
  1333. }
  1334. /* buffer_empty */
  1335.  
  1336. int
  1337. controls
  1338. #ifdef __STDC__
  1339.   (int npts, FILE * figfp)
  1340. #else
  1341.   (npts, figfp)
  1342.   int npts;
  1343.   FILE * figfp;
  1344. #endif
  1345. /* npts = number of ordinary points */
  1346. {
  1347.   extern MsgType Message;
  1348.   int ncontrols = 0;    /* number of control points, should be 2*npts. */
  1349.   int more = TRUE;  /* any more coordinates? */
  1350.   int i;
  1351.   char * bufp = buf;   /* pointer to current buffer position */
  1352.  
  1353.   /* Read control points line from Fig file into buffer */
  1354.   next_src_line (figfp);
  1355.  
  1356.   for (i=0; more && i < npts; i++)
  1357.   {
  1358.     double lx, ly, rx, ry;  /* control points are floating point */
  1359.     int n;
  1360.  
  1361.     /* read X and Y coordinates of left and right control points */
  1362.     if (!get_double (figfp, &bufp, &lx))
  1363.     {
  1364.       put_msg ("Missing Left control X coordinate (expect a number),");
  1365.       sprintf (Message, "  for point %d, ", i+1);
  1366.       Lwrite (Message);
  1367.       sprintf (Message, "coord. after byte %ld in line.\n", bufp - buf);
  1368.       Lwrite (Message);
  1369.       Lflush ();
  1370.       more = FALSE;
  1371.     }
  1372.     else if (!get_double (figfp, &bufp, &ly))
  1373.     {
  1374.       put_msg ("Missing Left control Y coordinate (expect a number),");
  1375.       sprintf (Message, "  for point %d, ", i+1);
  1376.       Lwrite (Message);
  1377.       sprintf (Message, "coord. after byte %ld in line.\n", bufp - buf);
  1378.       Lwrite (Message);
  1379.       Lflush ();
  1380.       more = FALSE;
  1381.     }
  1382.     else if (!get_double (figfp, &bufp, &rx))
  1383.     {
  1384.       put_msg ("Missing Right control X coordinate (expect a number),");
  1385.       sprintf (Message, "  for point %d, ", i+1);
  1386.       Lwrite (Message);
  1387.       sprintf (Message, "coord. after byte %ld in line.\n", bufp - buf);
  1388.       Lwrite (Message);
  1389.       Lflush ();
  1390.       more = FALSE;
  1391.     }
  1392.     else if (!get_double (figfp, &bufp, &ry))
  1393.     {
  1394.       put_msg ("Missing Right control Y coordinate (expect a number),");
  1395.       sprintf (Message, "  for point %d, ", i+1);
  1396.       Lwrite (Message);
  1397.       sprintf (Message, "coord. after byte %ld in line.\n", bufp - buf);
  1398.       Lwrite (Message);
  1399.       Lflush ();
  1400.       more = FALSE;
  1401.     }
  1402.     else
  1403.     {
  1404.       if (bbbegun)
  1405.       {
  1406.         bxl = MIN (bxl, lx);    bxl = MIN (bxl, rx);
  1407.         bxu = MAX (bxu, lx);    bxu = MAX (bxu, rx);
  1408.         byl = MIN (byl, ly);    byl = MIN (byl, ry);
  1409.         byu = MAX (byu, ly);    byu = MAX (byu, ry);
  1410.       }
  1411.       else
  1412.       {
  1413.         bxl = MIN (lx, rx);
  1414.         bxu = MAX (lx, rx);
  1415.         byl = MIN (ly, ry);
  1416.         byu = MAX (ly, ry);
  1417.         bbbegun = 1;
  1418.       }
  1419.  
  1420.       /* write control point coordinates to TeX file */
  1421.  
  1422.       if (ncontrols > 0)
  1423.         OUTPUT (",\n");
  1424.       OUTPUT ("       (%lf, %lf), (%lf, %lf)",
  1425.               xt(lx), yt(ly), xt(rx), yt(ry));
  1426.       ++ ncontrols;
  1427.       more = TRUE;
  1428.     } /* (outer) fi */
  1429.   } /* end (for) loop */
  1430.  
  1431.   if (ncontrols < 1)
  1432.   {
  1433.     put_msg ("No control points");
  1434.   }
  1435.   return ncontrols;
  1436. }
  1437. /* controls */
  1438.  
  1439.  
  1440. /* Text objects */
  1441. /* Maximum length of text */
  1442. #define TEXT_SLEN  80
  1443.  
  1444. /* text justification (text subtypes) */
  1445.  
  1446. #define T_LEFT_JUSTIFIED    0
  1447. #define T_CENTER_JUSTIFIED  1
  1448. #define T_RIGHT_JUSTIFIED   2
  1449.  
  1450. /* (orthogonal) properties of text, stored as separate bits in text_flags */
  1451.  
  1452. #define NO_TEXT       0
  1453. #define RIGID_TEXT    1
  1454. #define SPECIAL_TEXT  2
  1455. #define PSFONT_TEXT   4
  1456. #define HIDDEN_TEXT   8
  1457.  
  1458. /* default font values */
  1459.  
  1460. #define DEFAULT_FONT_0  0
  1461. #define DEFAULT_FONT_1  (-1)
  1462.  
  1463. /* general fonts */
  1464. /* `modern' means `sans serif' */
  1465.  
  1466. #define ROMAN  1
  1467. #define BOLD  2
  1468. #define ITALICS  3
  1469. #define MODERN  4
  1470. #define TYPEWRITER  5
  1471.  
  1472. /* PostScript fonts (the common 35) */
  1473.  
  1474. #define TR  1
  1475. #define TI  2
  1476. #define TB  3
  1477. #define TBI  4
  1478.  
  1479. #define AG  5
  1480. #define AGBO  6
  1481. #define AGD  7
  1482. #define AGDO  8
  1483.  
  1484. #define BKL  9
  1485. #define BKLI  10
  1486. #define BKD  11
  1487. #define BKDI  12
  1488.  
  1489. #define COUR  13
  1490. #define COURO  14
  1491. #define COURB  15
  1492. #define COURBI  16
  1493.  
  1494. #define HV  17
  1495. #define HVO  18
  1496. #define HVB  19
  1497. #define HVBO 20
  1498.  
  1499. #define HVN  21
  1500. #define HVNO  22
  1501. #define HVNB  23
  1502. #define HVNBO  24
  1503.  
  1504. #define NCR  25
  1505. #define NCI  26
  1506. #define NCB  27
  1507. #define NCBI  28
  1508.  
  1509. #define PLR  29
  1510. #define PLI  30
  1511. #define PLB  31
  1512. #define PLBI  32
  1513.  
  1514. #define SYMBOL  33
  1515.  
  1516. #define ZCMI  34
  1517.  
  1518. #define ZDING  35
  1519.  
  1520.  
  1521. int
  1522. text
  1523. #ifdef __STDC__
  1524.   (FILE * figfp)
  1525. #else
  1526.   (figfp)
  1527.   FILE * figfp;
  1528. #endif
  1529. {
  1530.   extern MsgType Message;
  1531.   int    type,
  1532.          subtype,
  1533.          font;
  1534.   double  font_size;
  1535.   int    pen,
  1536.          color,
  1537.          depth;
  1538.   double  angle;
  1539.   int    text_flags;
  1540.   double  ht,
  1541.           len;
  1542.   int    x,
  1543.          y;
  1544.   char   text[TEXT_SLEN+1];
  1545.  
  1546.   /* alignment of text (baseline left is the default) */
  1547.   char * orient = "bl";
  1548.  
  1549.   /* Full name of font requested in the Fig file */
  1550.   char * font_name = "DEFAULT FONT";
  1551.  
  1552.   /* TeX font used to simulate font requested in the Fig file */
  1553.   char * tex_font = "\\tt";
  1554.  
  1555.   /* _estimated_ text bounding box */
  1556.   int txl, txu, tyl, tyu;
  1557.  
  1558.   int    n;
  1559.  
  1560.   /* eat whitespace before text string */
  1561.   n = sscanf (buf, "%d%d%d%lf%d%d%d%lf%d%lf%lf%d%d %[^\1]",
  1562.       &type,
  1563.       &subtype,
  1564.       &font,
  1565.       &font_size,
  1566.       &pen,
  1567.       &color,
  1568.       &depth,
  1569.       &angle,
  1570.       &text_flags,
  1571.       &ht,
  1572.       &len,
  1573.       &x,
  1574.       &y,
  1575.       text);
  1576.   if (n != N_TEXT)
  1577.   {
  1578.     put_msg ("Bad Text");
  1579.     return (0);  /* Like a zero length string - a doubtful value? */
  1580.   }
  1581.  
  1582.   switch (subtype)
  1583.   {
  1584.     case T_LEFT_JUSTIFIED:
  1585.       orient = "bl";
  1586.       txl = x;
  1587.       break;
  1588.     case T_CENTER_JUSTIFIED:
  1589.       orient = "bc";
  1590.       txl = x - len/2;
  1591.       break;
  1592.     default:
  1593.       sprintf (Message,
  1594.         "\"%d\" is an unknown text justification\n", subtype);
  1595.       put_msg (Message);
  1596.       /* default to right justification */
  1597.     case T_RIGHT_JUSTIFIED:
  1598.       orient = "br";
  1599.       txl = x - len;
  1600.       break;
  1601.     break;
  1602.   }
  1603.  
  1604.  
  1605.   if (text_flags & PSFONT_TEXT)
  1606.   {
  1607.  
  1608.     /* PostScript fonts */
  1609.     switch (font)
  1610.     {
  1611.       case DEFAULT_FONT_0:
  1612.       case DEFAULT_FONT_1:
  1613.           font_name = "DEFAULT PostScript";
  1614.           tex_font = "\\tt";
  1615.         break;
  1616.       case TR:
  1617.           font_name = "Times-Roman";
  1618.           tex_font = "\\rm";
  1619.         break;
  1620.       case TI:
  1621.           font_name = "Times-Italic";
  1622.           tex_font = "\\it";
  1623.         break;
  1624.       case TB:
  1625.           font_name = "Times-Bold";
  1626.           tex_font = "\\bf";
  1627.         break;
  1628.       case TBI:
  1629.           font_name = "Times-Bold-Italic";
  1630.           tex_font = "\\it";
  1631.         break;
  1632.       case AG:
  1633.           font_name = "AvantGarde";
  1634.           tex_font = "\\rm";
  1635.         break;
  1636.       case AGBO:
  1637.           font_name = "AvantGarde-BookOblique";
  1638.           tex_font = "\\sl";
  1639.         break;
  1640.       case AGD:
  1641.           font_name = "AvantGarde-Demi";
  1642.           tex_font = "\\bf";
  1643.         break;
  1644.       case AGDO:
  1645.           font_name = "AvantGarde-DemiOblique";
  1646.           tex_font = "\\sl";
  1647.         break;
  1648.       case BKL:
  1649.           font_name = "Bookman-Light";
  1650.           tex_font = "\\rm";
  1651.         break;
  1652.       case BKLI:
  1653.           font_name = "Bookman-LightItalic";
  1654.           tex_font = "\\it";
  1655.         break;
  1656.       case BKD:
  1657.           font_name = "Bookman-Demi";
  1658.           tex_font = "\\bf";
  1659.         break;
  1660.       case BKDI:
  1661.           font_name = "Bookman-DemiItalic";
  1662.           tex_font = "\\it";
  1663.         break;
  1664.       case COUR:
  1665.           font_name = "Courier";
  1666.           tex_font = "\\tt";
  1667.         break;
  1668.       case COURO:
  1669.           font_name = "Courier-Oblique";
  1670.           tex_font = "\\tt";
  1671.         break;
  1672.       case COURB:
  1673.           font_name = "Courier-Bold";
  1674.           tex_font = "\\tt";
  1675.         break;
  1676.       case COURBI:
  1677.           font_name = "Courier-BoldItalic";
  1678.           tex_font = "\\tt";
  1679.         break;
  1680.       case HV:
  1681.           font_name = "Helvetica";
  1682.           tex_font = "\\sf";
  1683.         break;
  1684.       case HVO:
  1685.           font_name = "Helvetica-Oblique";
  1686.           tex_font = "\\sf";
  1687.         break;
  1688.       case HVB:
  1689.           font_name = "Helvetica-Bold";
  1690.           tex_font = "\\sf";
  1691.         break;
  1692.       case HVBO:
  1693.           font_name = "Helvetica-BoldOblique";
  1694.           tex_font = "\\sf";
  1695.         break;
  1696.       case HVN:
  1697.           font_name = "Helvetica-Narrow";
  1698.           tex_font = "\\sf";
  1699.         break;
  1700.       case HVNO:
  1701.           font_name = "Helvetica-Narrow-Oblique";
  1702.           tex_font = "\\sf";
  1703.         break;
  1704.       case HVNB:
  1705.           font_name = "Helvetica-Narrow-Bold";
  1706.           tex_font = "\\sf";
  1707.         break;
  1708.       case HVNBO:
  1709.           font_name = "Helvetica-Narrow-BoldOblique";
  1710.           tex_font = "\\sf";
  1711.         break;
  1712.       case NCR:
  1713.           font_name = "NewCenturySchlbk-Roman";
  1714.           tex_font = "\\rm";
  1715.         break;
  1716.       case NCI:
  1717.           font_name = "NewCenturySchlbk-Italic";
  1718.           tex_font = "\\it";
  1719.         break;
  1720.       case NCB:
  1721.           font_name = "NewCenturySchlbk-Bold";
  1722.           tex_font = "\\bf";
  1723.         break;
  1724.       case NCBI:
  1725.           font_name = "NewCenturySchlbk-BoldItalic";
  1726.           tex_font = "\\it";
  1727.         break;
  1728.       case PLR:
  1729.           font_name = "Palatino-Roman";
  1730.           tex_font = "\\rm";
  1731.         break;
  1732.       case PLI:
  1733.           font_name = "Palatino-Italic";
  1734.           tex_font = "\\it";
  1735.         break;
  1736.       case PLB:
  1737.           font_name = "Palatino-Bold";
  1738.           tex_font = "\\bf";
  1739.         break;
  1740.       case PLBI:
  1741.           font_name = "Palatino-BoldItalic";
  1742.           tex_font = "\\it";
  1743.         break;
  1744.       case SYMBOL:  /* wrong characters, but what to do? */
  1745.           font_name = "Symbol";
  1746.           tex_font = "\\tt";
  1747.         break;
  1748.       case ZCMI:    /* wrong characters, but what to do? */
  1749.           font_name = "ZapfChancery-MediumItalic";
  1750.           tex_font = "\\tt";
  1751.         break;
  1752.       case ZDING:   /* wrong characters, but what to do? */
  1753.           font_name = "ZapfDingbats";
  1754.           tex_font = "\\tt";
  1755.         break;
  1756.       default:     /* fall back to typewriter type */
  1757.           font_name = "INVALID PostScript";
  1758.           tex_font = "\\tt";
  1759.         break;
  1760.     }
  1761.  
  1762.   }
  1763.   else
  1764.   {
  1765.  
  1766.     /* general fonts */
  1767.     switch (font)
  1768.     {
  1769.       case DEFAULT_FONT_0:
  1770.       case DEFAULT_FONT_1:
  1771.           font_name = "DEFAULT Fig";
  1772.           tex_font = "\\tt";
  1773.         break;
  1774.       case ROMAN:
  1775.           font_name = "Roman";
  1776.           tex_font = "\\rm";
  1777.         break;
  1778.       case BOLD:
  1779.           font_name = "Bold";
  1780.           tex_font = "\\bf";
  1781.         break;
  1782.       case ITALICS:
  1783.           font_name = "Italics";
  1784.           tex_font = "\\it";
  1785.         break;
  1786.       case MODERN:
  1787.           font_name = "Modern (sans serif)";
  1788.           tex_font = "\\sf";
  1789.         break;
  1790.       case TYPEWRITER:
  1791.           font_name = "Typewriter";
  1792.           tex_font = "\\tt";
  1793.         break;
  1794.       default:     /* fall back to typewriter type */
  1795.           font_name = "INVALID Fig";
  1796.           tex_font = "\\tt";
  1797.         break;
  1798.     }
  1799.  
  1800.   }
  1801.  
  1802.   /* completion of calculation of _estimated_ text bounding box */
  1803.   txu = txl + len;
  1804.   tyl = y;
  1805.   tyu = tyl + ht;
  1806.  
  1807.   /* _estimated_ Bounding Box for picture, including this text */
  1808.   if (bbbegun)
  1809.   {
  1810.     bxl = MIN (bxl, txl);
  1811.     bxu = MAX (bxu, txu);
  1812.     byl = MIN (byl, tyl);
  1813.     byu = MAX (byu, tyu);
  1814.   }
  1815.   else
  1816.   {
  1817.     bxl = txl;
  1818.     bxu = txu;
  1819.     byl = tyl;
  1820.     byu = tyu;
  1821.     bbbegun = 1;
  1822.   }
  1823.  
  1824.   OUTPUT ("%% - %s font at %.3lf pt\n", font_name, font_size);
  1825.  
  1826.   /* mfpic label */
  1827.   OUTPUT ("  \\label[%s]{%lf}{%lf}{%s %s}\n",
  1828.                orient, xt(x), yt(y), tex_font, text);
  1829.  
  1830.   return (strlen (text));
  1831. }
  1832. /* text */
  1833.  
  1834.  
  1835. /* Arc objects */
  1836. /* The only arc subtype in Fig 2.1 is a three-point arc */
  1837. #define T_3_POINT_ARC  1
  1838.  
  1839. int
  1840. arc
  1841. #ifdef __STDC__
  1842.   (FILE * figfp)
  1843. #else
  1844.   (figfp)
  1845.   FILE * figfp;
  1846. #endif
  1847. {
  1848.   int  n;
  1849.   int  type,
  1850.        subtype,
  1851.        line_style,
  1852.        line_thickness,
  1853.        color,
  1854.        depth,
  1855.        pen,
  1856.        fill;
  1857.   double  style_val;
  1858.   int  dir,
  1859.        fa,
  1860.        ba;
  1861.   double  cx,
  1862.           cy;
  1863.   int  x1,
  1864.        y1,
  1865.        x2,
  1866.        y2,
  1867.        x3,
  1868.        y3;
  1869.  
  1870.   n = sscanf (buf, "%d%d%d%d%d%d%d%d%lf%d%d%d%lf%lf%d%d%d%d%d%d",
  1871.     &type,
  1872.     &subtype,
  1873.     &line_style,
  1874.     &line_thickness,
  1875.     &color,
  1876.     &depth,
  1877.     &pen,
  1878.     &fill,
  1879.     &style_val,
  1880.     &dir,
  1881.     &fa,
  1882.     &ba,
  1883.     &cx,
  1884.     &cy,
  1885.     &x1,
  1886.     &y1,
  1887.     &x2,
  1888.     &y2,
  1889.     &x3,
  1890.     &y3);
  1891.  
  1892.   if (fa) next_src_line (figfp);
  1893.   if (ba) next_src_line (figfp);
  1894.  
  1895.   if (n != N_ARC)
  1896.   {
  1897.     put_msg ("Malformed arc");
  1898.     return n;
  1899.   }
  1900.  
  1901.   /* arc bounding box */
  1902.   {
  1903.     int cxl, cxu, cyl, cyu;
  1904.     int axl, axu, ayl, ayu;
  1905.  
  1906.     int dx1 = x1 - cx;
  1907.     int dy1 = y1 - cy;
  1908.     double r = hypot (dx1, dy1);
  1909.     double cos1 = dx1 / r;
  1910.     double sin1 = dy1 / r;
  1911.     double cos3 = (x3 - cx) / r;
  1912.     double sin3 = (y3 - cy) / r;
  1913.     int ir = (int) ceil (r);
  1914.     
  1915.     /* left, right, bottom and top of circle of which arc is part */
  1916.     cxl = cx - ir;
  1917.     cxu = cx + ir;
  1918.     cyl = cy - ir;
  1919.     cyu = cy + ir;
  1920.  
  1921.     /* ! temporary, crude estimate, based on including whole circle */
  1922.     axl = cxl;
  1923.     axu = cxu;
  1924.     ayl = cyl;
  1925.     ayu = cyu;
  1926.  
  1927.     if (bbbegun)
  1928.     {
  1929.       bxl = MIN (bxl, axl);
  1930.       bxu = MAX (bxu, axu);
  1931.       byl = MIN (byl, ayl);
  1932.       byu = MAX (byu, ayu);
  1933.     }
  1934.     else
  1935.     {
  1936.       bxl = axl;
  1937.       bxu = axu;
  1938.       byl = ayl;
  1939.       byu = ayu;
  1940.       bbbegun = 1;
  1941.     }
  1942.   }
  1943.  
  1944.   if (line_thickness > 1)
  1945.     OUTPUT ("  \\pen{%.2lfpt}\n", do_pen (line_thickness));
  1946.  
  1947.   OUTPUT ("  \\mfcmd {arcthree((%lf,%lf), (%lf,%lf), (%lf,%lf))} \n",
  1948.     xt(x1), yt(y1),
  1949.     xt(x2), yt(y2),
  1950.     xt(x3), yt(y3));
  1951.  
  1952.   if (line_thickness > 1)
  1953.     OUTPUT ("  \\pen{%.2lfpt}\n", mfpen);
  1954.  
  1955.   return n;
  1956. }
  1957. /* arc */
  1958.  
  1959.  
  1960. /* Compound objects */
  1961. /* Write a TeX comment, and, if necessary, extend the bounding box */ 
  1962.  
  1963. int
  1964. compound
  1965. #ifdef __STDC__
  1966.   (FILE * figfp)
  1967. #else
  1968.   (figfp)
  1969.   FILE * figfp;
  1970. #endif
  1971. {
  1972.   int cxl, cxu, cyl, cyu;
  1973.   int n;
  1974.  
  1975.   n = sscanf (buf, "%d%d%d%d", &cxl, &cxu, &cyl, &cyu);
  1976.   if (n != N_COMPOUND)
  1977.   {
  1978.     put_msg ("Malformed compound");
  1979.     return n;
  1980.   }
  1981.  
  1982.   OUTPUT ("%% Compound.\n");
  1983.  
  1984.   if (bbbegun)
  1985.   {
  1986.     bxl = MIN (bxl, cxl);
  1987.     bxu = MAX (bxu, cxu);
  1988.     byl = MIN (byl, cyl);
  1989.     byu = MAX (byu, cyu);
  1990.   }
  1991.   else
  1992.   {
  1993.     bxl = cxl;
  1994.     bxu = cxu;
  1995.     byl = cyl;
  1996.     byu = cyu;
  1997.     bbbegun = 1;
  1998.   }
  1999.  
  2000.   return n;
  2001. }
  2002. /* compound */
  2003.  
  2004.  
  2005. /* End compound objects */
  2006. /* Only write a comment */
  2007.  
  2008. int
  2009. end_compound
  2010. #ifdef __STDC__
  2011.   (FILE * figfp)
  2012. #else
  2013.   (figfp)
  2014.   FILE * figfp;
  2015. #endif
  2016. {
  2017.   OUTPUT ("%% End Compound.\n");
  2018. }
  2019. /* end_compound */
  2020.  
  2021.  
  2022. /* return name of object subtype from given type and subtype codes */
  2023. char *
  2024. subtype_name
  2025. #ifdef __STDC__
  2026.   (int type, int subtype)
  2027. #else
  2028.   (type, subtype)
  2029.   int type, subtype;
  2030. #endif
  2031. {
  2032.   char * sub_name = "unknown";
  2033.  
  2034.   switch (type)
  2035.   {
  2036.     case O_ELLIPSE:
  2037.       switch (subtype)
  2038.       {
  2039.         case T_ELLIPSE_BY_RAD:
  2040.           sub_name = "ellipse by radius";
  2041.           break;
  2042.         case T_ELLIPSE_BY_DIA:
  2043.           sub_name = "ellipse by diameter";
  2044.           break;
  2045.         case T_CIRCLE_BY_RAD:
  2046.           sub_name = "circle by radius";
  2047.           break;
  2048.         case T_CIRCLE_BY_DIA:
  2049.           sub_name = "circle by diameter";
  2050.           break;
  2051.         default:
  2052.           sub_name = "unknown ellipse";
  2053.           break;
  2054.       }
  2055.       break;
  2056.     case O_POLYLINE:
  2057.       switch (subtype)
  2058.       {
  2059.         case T_POLYLINE:
  2060.           sub_name = "polyline";
  2061.           break;
  2062.         case T_BOX:
  2063.           sub_name = "box";
  2064.           break;
  2065.         case T_POLYGON:
  2066.           sub_name = "polygon";
  2067.           break;
  2068.         case T_ARC_BOX:
  2069.           sub_name = "arc box";
  2070.           break;
  2071.         case T_EPS_BOX:
  2072.           sub_name = "EPS box";
  2073.           break;
  2074.         default:
  2075.           sub_name = "unknown polyline";
  2076.           break;
  2077.       }
  2078.       break;
  2079.     case O_SPLINE:
  2080.       switch (subtype)
  2081.       {
  2082.         case T_OPEN_NORMAL:
  2083.           sub_name = "open normal spline (open B-spline)";
  2084.           break;
  2085.         case T_CLOSED_NORMAL:
  2086.           sub_name = "closed normal spline (closed B-spline)";
  2087.           break;
  2088.         case T_OPEN_INTERPOLATED:
  2089.           sub_name = "open interpolated spline";
  2090.           break;
  2091.         case T_CLOSED_INTERPOLATED:
  2092.           sub_name = "open interpolated spline";
  2093.           break;
  2094.         default:
  2095.           sub_name = "unknown spline";
  2096.           break;
  2097.       }
  2098.       break;
  2099.     case O_TEXT:
  2100.       switch (subtype)
  2101.       {
  2102.         case T_LEFT_JUSTIFIED:
  2103.           sub_name = "left justified text";
  2104.           break;
  2105.         case T_CENTER_JUSTIFIED:
  2106.           sub_name = "center justified text";
  2107.           break;
  2108.         case T_RIGHT_JUSTIFIED:
  2109.           sub_name = "right justified text";
  2110.           break;
  2111.         default:
  2112.           sub_name = "unknown text justification";
  2113.           break;
  2114.       }
  2115.       break;
  2116.     case O_ARC:
  2117.       switch (subtype)
  2118.       {
  2119.         case T_3_POINT_ARC:
  2120.           sub_name = "three-point arc";
  2121.           break;
  2122.         default:
  2123.           sub_name = "unknown arc";
  2124.           break;
  2125.       }
  2126.       break;
  2127.     case O_COMPOUND:
  2128.       sub_name = "compound";
  2129.       break;
  2130.     case O_END_COMPOUND:
  2131.       sub_name = "end compound";
  2132.       break;
  2133.     default:
  2134.       sub_name = "unknown";
  2135.       break;
  2136.   }
  2137.   return (sub_name);
  2138. }
  2139. /* subtype_name */
  2140.  
  2141.  
  2142. static int curchar = FIRST_CHAR;  /* assignment here is not important */
  2143.  
  2144. Void finit (VOID)
  2145. {
  2146.   curchar = char_code;
  2147.   OUTPUT ("%%\n");
  2148.   OUTPUT ("%% gt fig2mfpic version %s for mfpic %s and graphbase %s\n",
  2149.           VERSION, MFPIC_VERSION, GRAPHBASE_VERSION);
  2150.   OUTPUT ("%% compiled as %s", progname);
  2151. #ifdef __STDC__
  2152.   OUTPUT (" from file %s on %s %s", __FILE__, __DATE__, __TIME__);
  2153. #endif
  2154.   OUTPUT ("\n");
  2155.   OUTPUT ("%% --- Preamble\n");
  2156.   OUTPUT ("%%\n");
  2157.   /* test whether drawing macros (eg, "mfpic.tex") have been input */
  2158.   OUTPUT ("\\ifx\\opengraphsfile\\undefined\n");
  2159.   /* if they have not, assume output is intended as a stand-alone TeX file */
  2160.   OUTPUT ("  \\def\\endfigtomfpic{\\par\\vfill\\supereject\\end}");
  2161.   OUTPUT ("  %% like bye, but not outer.\n");
  2162.   OUTPUT ("  \\message{You didn't input the drawing macros,");
  2163.   OUTPUT (" so, Gw, I will.}\n");
  2164.   OUTPUT ("  \\message{NB:  I'll exit after closegraphsfile.}\n");
  2165.   OUTPUT ("%%\n");
  2166.   /* input drawing macros now */
  2167.   OUTPUT ("  \\input %s\n", draw_macros);
  2168.   OUTPUT ("%%\n");
  2169.   /* of course, the assumption might be wrong */
  2170.   /* but if the drawing macros were previously input */
  2171.   OUTPUT ("\\else\n");
  2172.   /* then this is an "encapsulated TeX" :-) file */
  2173.   OUTPUT ("  \\let\\endfigtomfpic=\\relax\n");
  2174.   OUTPUT ("\\fi\n");
  2175.   OUTPUT ("\\def\\polyline{\\polycurve}\n");
  2176.   OUTPUT ("%%\n");
  2177.   OUTPUT ("\\opengraphsfile{%s}\n", mf_ofile);
  2178.   define_polydash();
  2179. }
  2180. /* finit */
  2181.  
  2182. /* Augment the TeX and MF drawing macros with a dash polyline */
  2183. Void define_polydash (VOID)
  2184. {
  2185. #define BAD_KLUGE
  2186. #ifdef BAD_KLUGE
  2187.   /* ! temporary partial attempt */
  2188.   OUTPUT ("\\def\\polydash{\\dottedline}\n");
  2189. #else
  2190.   OUTPUT ("\\def\\polydash{%%\n");
  2191.   OUTPUT ("  \\mfcmd{%%\n");
  2192.   /* ! need something substantial here */
  2193.   OUTPUT ("    \n");
  2194.   OUTPUT ("  }%%\n");
  2195.   OUTPUT ("}%%\n");
  2196. #endif
  2197. }
  2198. /* define_polydash */
  2199.  
  2200. /* input picture <-> output character */
  2201. Void cinit (VOID)
  2202. {
  2203.   if (nchar < MAXNCHAR)
  2204.   {
  2205.     bbbegun = 0;  /* no bounding box estimate yet, for this picture */
  2206.     /* comment : current input file, and corresponding output character */
  2207.     OUTPUT ("%%\n%% \"%s\" (char %d)\n%%\n", curfigfile, curchar);
  2208.     /* X, Y drawing units (pt), picture bounding box (drawing units) */
  2209.     OUTPUT ("\\mfpic[%.4lf][%.4lf]{%.4lf}{%.4lf}{%.4lf}{%.4lf}\n",
  2210.       xscale / oupi * PT_PER_INCH,
  2211.       yscale / oupi * PT_PER_INCH,
  2212.       xl, xu, yl, yu);
  2213.   }
  2214. }
  2215. /* cinit */
  2216.  
  2217. #define DSWAP(x,y) {double temp = x; x = y; y = temp;}
  2218.  
  2219. Void cfin (VOID)
  2220. {
  2221.   OUTPUT ("\\endmfpic\n");
  2222.   /* bounding box comment, to replace estimate in cinit() */
  2223.   if (bbbegun)
  2224.   {
  2225.     double pxl, pxu, pyl, pyu;
  2226.     int xsgn = (xscale / oupi * PT_PER_INCH < 0.0 ? -1 : 1);
  2227.     int ysgn = (yscale / oupi * PT_PER_INCH < 0.0 ? -1 : 1);
  2228.  
  2229.     pxl = xt(bxl);
  2230.     pxu = xt(bxu);
  2231.     pyl = yt(byl);
  2232.     pyu = yt(byu);
  2233.  
  2234.     if (xsgn * pxl > xsgn * pxu)
  2235.       DSWAP (pxl, pxu);
  2236.     if (ysgn * pyl > ysgn * pyu)
  2237.       DSWAP (pyl, pyu);
  2238.  
  2239.     OUTPUT ("%% Bounding box is now estimated to be:\n");
  2240.     OUTPUT ("%% \\mfpic[%.4lf][%.4lf]{%.4lf}{%.4lf}{%.4lf}{%.4lf}\n",
  2241.       xscale / oupi * PT_PER_INCH,
  2242.       yscale / oupi * PT_PER_INCH,
  2243.       pxl, pxu, pyl, pyu);
  2244.   }
  2245.   OUTPUT ("%%\n%% end \"%s\" (char %d)\n%%\n", curfigfile, curchar);
  2246.   ++ nchar;
  2247.   ++ curchar;
  2248. }
  2249. /* cfin */
  2250.  
  2251. Void ffin (VOID)
  2252. {
  2253.   if (nchar > 0)
  2254.   {
  2255.     OUTPUT ("\\closegraphsfile\n");
  2256.     OUTPUT ("\\endfigtomfpic\n");
  2257.   }
  2258. }
  2259. /* ffin */
  2260.  
  2261. int
  2262. get_line
  2263. #ifdef __STDC__
  2264.   (FILE * figfp)
  2265. #else
  2266.   (figfp)
  2267.   FILE * figfp;
  2268. #endif
  2269. {
  2270.   /* Read next line of Fig file figfp, including linefeed, */
  2271.   /* into buffer of at most BUF_SIZE characters. */
  2272.  
  2273.   int retval;
  2274.  
  2275.   if (fgets (buf, BUF_SIZE, figfp) == NULL)
  2276.   {
  2277.     /* No line */
  2278.     retval = FALSE;
  2279.   }
  2280.   else
  2281.   {
  2282.     /* Count all lines */
  2283.     ++ linenum;
  2284.     if (debug)
  2285.     {
  2286.       display_line();
  2287.     }
  2288.     retval = TRUE;
  2289.   }
  2290.   return retval;
  2291. }
  2292. /* get_line */
  2293.  
  2294. int
  2295. next_src_line
  2296. #ifdef __STDC__
  2297.   (FILE * figfp)
  2298. #else
  2299.   (figfp)
  2300.   FILE * figfp;
  2301. #endif
  2302. {
  2303.   /* Read next non-empty, non-comment line of Fig file figfp, if any */
  2304.   int flag = 0;
  2305.   while (!flag)
  2306.   {
  2307.     if (!get_line (figfp))
  2308.       flag = -1;  /* No more lines */
  2309.     else if (*buf != '\n' && *buf != '#')
  2310.       flag = 1;   /* Good!  A non-empty, non-comment line */
  2311.     /* _Skip_ empty and comment lines */
  2312.   }
  2313.   return flag;  /* 1 or -1 */
  2314. }
  2315. /* next_src_line */
  2316.  
  2317. Void
  2318. display_line (VOID)
  2319. {
  2320.   MsgType LineNum;
  2321.  
  2322.   sprintf (LineNum, "Line %d: ", linenum);
  2323.   Lwrite (LineNum);
  2324.   Lwrite (buf);
  2325.   Lflush ();
  2326. }
  2327. /* display_line */
  2328.  
  2329. int
  2330. get_int
  2331. #ifdef __STDC__
  2332.   (char ** bufpa, int * ya)
  2333. #else
  2334.   (bufpa, ya)
  2335.   char ** bufpa;
  2336.   int * ya;
  2337. #endif
  2338. /*  bufpa = Address of (a buffer pointer : I/O). */
  2339. /*  ya    = Address of (a int : O). */
  2340. {
  2341.  
  2342.   /* Skip leading blanks of *bufpa, then try to read a decimal    */
  2343.   /* integer from it into ya, advancing bufpa while successful.   */ 
  2344.   /* Return TRUE if an integer is found, FALSE otherwise.         */
  2345.   /*............................................................. */
  2346.   /* It's hard to believe that traditional K&R has no convenient  */
  2347.   /* library function for this extremely common task.             */
  2348.   /* OR something like fscanf, that uses a data structure to keep */
  2349.   /* track of its current position, and has a variety of formats. */
  2350.   /*............................................................. */
  2351.  
  2352.   int found = FALSE;
  2353.   if (bufpa == NULL || *bufpa == NULL || ya == NULL)
  2354.   {
  2355.     put_msg ("About to dereference a NULL pointer");
  2356.     found = FALSE; 
  2357.   }
  2358.   else
  2359.   {
  2360.     char * start = *bufpa;
  2361.     *ya = (int) strtol (start, bufpa, 10);
  2362.     if (*bufpa != start)
  2363.       found = TRUE;
  2364.   }
  2365.   return (found);
  2366. }
  2367. /* get_int */
  2368.  
  2369. int
  2370. get_double
  2371. #ifdef __STDC__
  2372.   (FILE * figfp, char ** bufpa, double * ya)
  2373. #else
  2374.   (figfp, bufpa, ya)
  2375.   FILE * figfp;
  2376.   char ** bufpa;
  2377.   double * ya;
  2378. #endif
  2379. /*  figfp = Address of (a FILE buffer : I/O).     */
  2380. /*  bufpa = Address of (a buffer pointer : I/O).  */
  2381. /*  ya    = Address of (a double : O).            */
  2382. {
  2383.  
  2384.   /* Skip leading blanks of *bufpa, then try to read a floating        */
  2385.   /* point number from it into ya, advancing bufpa while successful.   */ 
  2386.   /* Return TRUE if a number is found, FALSE otherwise.                */
  2387.  
  2388.   int found = FALSE;
  2389.   if (bufpa == NULL || *bufpa == NULL || ya == NULL)
  2390.   {
  2391.     put_msg ("About to dereference a NULL pointer");
  2392.     found = FALSE; 
  2393.   }
  2394.   else
  2395.   {
  2396.     char * start;
  2397.     while (buffer_empty (*bufpa))
  2398.     {
  2399.       next_src_line (figfp);
  2400.       *bufpa = buf;
  2401.     }
  2402.     start = *bufpa;
  2403.     *ya = strtod (start, bufpa);
  2404.     if (*bufpa != start)
  2405.       found = TRUE;
  2406.   }
  2407.   return (found);
  2408. }
  2409. /* get_double */
  2410.  
  2411. /* end of fig2mfpic of Wed  8 Jun 1994 */
  2412.